<?php
// ----------------------------------------------------------------------
// Source file:  $Source: /cvsroot/pn-commerce/pn-commerce/definemachine.php,v $
//
// Last changes from:  $Author: landseer $
//
// Revision:           $Revision: 1.2 $
//
// Date of revision    $Date: 2004/08/25 05:53:23 $
//
// ----------------------------------------------------------------------
//
// DefineMachine 0.4
//
// Author : Frank Schummertz, frank.schummertz@landseer-stuttgart.de
//
// This program needs the right to write into the directory where it is installed
//
// What does this script do ?
// --------------------------
// It can do several things:
// 1. read all the .php files in a modules/mymodule/pnlang/xxx/ dir and compose a /pnlang/xxx/myfile.php with
//    all the defines used in /modules/mymodule/pnmyfile.php
// 2. create a global_xxx.txt from the pnlang/xxx/ files with all the defines found in the
//	format DEFINE,VALUE
// 3. read this global_xxx.txt to create the same language files as mentioned under 1.
//	(why this ? you only have to take care of one file with defines during development
//	instead of multiple. DefineMachine does the final work for you)
// 4. create a debug file that gives you an overview of the defines and the files the were found in
//
// How do I use it ?
// -----------------
// As a PN developer I assume that you have at least a local webserver to test your software.
// Copy it to a separate directory in your webservers root and point your browser to it.
// The DefineMachine needs write access in the directory where it is installed, all files will be
// written there only !!
// If you want to use the global_xxx.txt-feature, you must copy it to the pnlang/xxx/ dir by hand
// The same applies for the final defintione files created by DefineMachine.
//
// What else do I have to take care of ?
// -------------------------------------
// You should see the created files before using them (=copying to the pnlang/xxx/ dir).
// If DefineMachine finds a constant that has not been defined, you will see a remark
// in the file. In this case, the value will be set to the constant name itself:
// define("_CONSTANT","_CONSTANT");
//
// There is also problem with PHP or PN constants that contain a _ like HTTP_ADDR or _PNH_VERBATIMINPUT
// In these cases you will find a define _ADDR and _PNH_VERBATIMINPUT in the result files which should be
// removed.
//
// Bugs or ideas for enhancements ? Send an email to frank.schummertz@landseer-stuttgart.de
//
// Planned for future versions:
// ----------------------------
// * create an blacklist of _CONSTANTS that should be ignored (to avoid the HTTP_ADDR and _PNH_VERBATIMINPUT
//   problem
// * better userinterface
// * ???
//
// ----------------------------------------------------------------------
// LICENSE
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License (GPL)
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// To read the license please visit http://www.gnu.org/copyleft/gpl.html
// ----------------------------------------------------------------------

$_GET['definefiledir'];
$_GET['sourcefile'];
$_GET['debug'];
$_GET['global'];
$_GET['useglobal'];

define("_NAME","DefineMachine");
define("_VERSION","0.4");
define("_DATE","22.03.2003");

$files = array();

if ( $definefiledir OR $sourcefile OR $global OR $useglobal )
{
	$language = extractLanguage($definefiledir);
	$sourcedefs = ReadDefinesFromSource ($sourcefile);
	if( $sourcedefs != false)
	{
		if( $useglobal == 'on' )
		{
			// use the global_xxx.txt file in the dir
			$defines = ReadGlobalDefineFile( $definefiledir );
		}
		else
		{
			// read th defines from the dir
			$defines = ReadDefineFilesFromDir ($definefiledir, $debug, $filenames);
		}
		if( $defines != false )
		{
			if ($global == 'on')
			{
				// create global_define_xxx.txt
				$gb = fopen ( "global_$language.txt", "w" );
				if ($gb)
				{
					for($x=0;$x<sizeof($defines);$x++)
					{ 
						fputs( $gb, sprintf("%s,%s\n",  key($defines), current($defines) ) ); 
						next($defines);
					}
					echo "<br>global_$language.txt written\n";
				}
				else
				{
					echo "<br>error writing global_$language.txt";
				}
			}
			// now the real work starts
			// save the lang file
			$new = basename ($sourcefile)."_".$language.".php";
			$fp = fopen ($new, "w");
			if( $fp )
			{
				if ( $useglobal == 'on' )
				{
					$definefiledir .= "/global_$language.txt";
				}
				fputs ($fp, "<?php\n\n// made with "._NAME." "._VERSION." (c) Frank Schummertz, frank.schummertz@landseer-stuttgart.de, "._DATE."\n// sourcefile : $sourcefile \n// defines read from $definefiledir\n// file created on ".date('l dS F Y H:i:s')."\n\n");
				foreach ($sourcedefs as $sourcedefline)
				{
					if ( empty( $defines[$sourcedefline] ) )
					{
						fputs( $fp, "// THE FOLLOWING LINE NEEDS YOUR ATTENTION\n");
						fputs( $fp, "if( !defined( $sourcedefline ) ) { define('$sourcedefline', '$sourcedefline'); }\n");
					}
					else
					{
						fputs( $fp, "if( !defined( $sourcedefline ) ) { define( '$sourcedefline', '$defines[$sourcedefline]' ); }\n");
					}
				}
				fputs ($fp, "\n?>");
				fclose( $fp );
				echo "<br>new file $new written, please check!<br>";
			}
			else
			{
				// error
				echo "could not open file $new for output - please check permissions<br>*** STOP";
			}
		}
		else
		{
			// error
			echo "*** error reading define file(s) - STOP";
		}
	}
	else
	{
		// error
		echo "*** error reading source file - STOP";
	}
}
else
{
	echo "
	<!doctype html public '-//W3C//DTD HTML 4.01 Transitional//EN'>
	<html>
	<head>
	    <title>"._NAME." "._VERSION."</title>
	    <meta name='Author' content='Frank Schummertz'>
	    <meta name='Date' content='Sun, 16 Mar 2003 13:00:00 GMT'>
	</head>
	<body>
	<h1>Welcome to "._NAME." "._VERSION." ("._DATE.")</h1>
	<h5>(c) <a href='mailto:frank.schummertz@landseer-stuttgart.de?subject="._NAME." "._VERSION."'>Frank Schummertz</a></h5>
	<table>
	<form><!-- enctype='multipart/form-data'-->
	<tr>
	<td>Enter path to all your language definition files :</td>
	<td><input name='definefiledir' type='text' size='100' value='/usr/local/httpd/htdocs/modules/pncommerce/pnlang/deu'></td>
	</tr>
	<tr>
	<td>Choose the source file :</td>
	<td><input name='sourcefile' type='text' size='100' value='/usr/local/httpd/htdocs/modules/pncommerce'></td>
	</tr>
	<tr>
	<td>Debug mode (shows source of define in separate file /path_to_definemachines/definemachine_language_debug.txt) :</td>
	<td><input name='debug' type='checkbox' value='on'></td>
	</tr>
	<tr>
	<td>Create global_xxx.txt file :</td>
	<td><input name='global' type='checkbox' value='on'></td>
	</tr>
	<tr>
	<td>Use previously created global_xxx.txt file :</td>
	<td><input name='useglobal' type='checkbox' value='on'></td>
	</tr>
	<tr>
	<td colspan='2'>
     	<br><br><INPUT class='button' TYPE='submit' NAME='Submit' VALUE='GO !'>
	</td>
	</tr>
	</form>
	</table>
	</body>
	</html>
	";
}

function ReadDefinesFromSource ($file)
{
	$valid = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567980";
	$valid2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
	
	$lines = array();
	$found = array();
	
	if ( file_exists ($file) )
	{
		echo "reading sourcefile $sourcefile<br>";
		$lines = file ($file);
		echo count($lines)." lines read from $file<br>";
		foreach ($lines as $line)
		// now the real work starts...
		{
			$line = strip_tags ($line);
			if ( substr_count ($line, "_") > 0 )
			{
				while ( substr_count ($line, "_") > 0 )
				{
					// forget everything left from the _
					$line = strchr ($line, "_");
					// if the next char is uppercase, it is a define
					// _ is now at pos. 0 so we check pos. 1
					$c2 = substr ($line, 1, 1);
					if ( substr_count ($valid2, $c2) > 0 )
					{
						// now find the next char that is not ABC...XYZ uppercase !!
						// this marks the end of the define
						// then copy everything from the start till this char to $define
						$define = substr ($line, 0 ,strspn ($line, $valid));
						// now replace the define found in $line with nothing -> remove it from $line
						$line = ereg_replace ($line, $define, "");
						// add the found define to the array
						$found[] = $define;
					}
					else
					{
						// 2nd char is not valid, kill the _ and continue search
						$line = ereg_replace ("_", "", $line);
					}
				}
			}
		}
		unset ($lines);
		$total = count($found);
		$found = array_unique ($found);
		asort ($found);	
		echo count($found)." unique defines from a total of $total found in $file<br><br>";
		return $found;
	}
	else
	{
		return false;
	}
}

function ReadDefineFilesFromDir ($definefiledir, $debug, &$filenames)
{
	$lines = array();
	$filesread = 0;

	if ( is_dir($definefiledir) )
	{
		$language = extractLanguage ($definefiledir);
		echo "start reading define files from $definefiledir<br>";
		$dir = opendir ( $definefiledir );
		$count = 0;
		if ( $debug == 'on' )
		{
			// open debug file
			$new = "definemachine_$language_debug.txt";
			$db = fopen ($new, "w");
		}
		while ( $file = readdir( $dir ) )
      	{
      		if ( (!empty($file)) & ( substr_count( $file, ".php") == 1) )
      		{
      			$filenames[$count] = $file;
				$file = $definefiledir."/".$file;
				$lines = file ($file);
				$filesread++;
				echo count($lines)." lines read from $file, ";
				foreach ($lines as $line)
				// now the real work starts...
				{
					if ( strlen ($line) > 0 )
					{
						// length of line is > 0
						if ( preg_match_all ("/\"(.+?)\"/", $line, $strings) )
						{
							// see if defines are saved in the normal way
							$found[$strings[1][0]] = $strings[1][1];
							if ($debug == 'on' )
							{
								// write debug file
								$fileonly = basename($file);
								fputs( $db, sprintf ("'%s' with value '%s' found in %s\n", $strings[1][0], $strings[1][1], "$language/$fileonly" ));
							}
						}
					}
				}
				unset ($lines);
				$count++;
				echo count($found)." define(s) found until now<br>"; 
			}
		}
		if ($debug == 'on' )
		{
			// close debug file
			fclose ($db);
			echo "debugfile $new written<br>";
		}
		$total = count($found);
		echo "*** a total of $total defines have been found in $filesread files in $definefiledir<br>";
		ksort ($found);
		return $found;
	}
	else
	{
		echo "supplied value is not a directory or does not exist<br>";
		return false;
	}
}

function ReadGlobalDefineFile ($dir)
{
	$lines = array();
	if ( is_dir($dir) )
	{
		$language = extractLanguage($dir);
		$file = $dir."/global_$language.txt";
		echo "reading defines from global define file<br>";
		$lines = file ($file);
		echo count($lines)." lines read from $file, ";
		foreach ($lines as $line)
		{
			// now the real work starts...
			if ( strlen ($line) > 0 )
			{
				// length of line is > 0
				// see if line starts with // as a remark
				if ( strpos( $line, "//" ) == false )
				{
					// no // found at the beginning -> no comment
					$split = explode (",", trim($line));
					$found[$split[0]] = $split[1];
				}
			}
		}
		unset ($lines);
		$total = count($found);
		echo "<br>$total defines found in $filesread files in $file<br>";
		ksort ($found);
		return $found;
	}
	else
	{
		echo "supplied value is not a directory or does not exist<br>";
		return false;
	}
}

function extractLanguage ($dir)
{
	return str_replace( "/", "", strrchr( $dir, "/" ) );
}
?>